//
// Created by Administrator on 2017/4/17.
//

#ifndef CARAR_RECNOTIFY_H
#define CARAR_RECNOTIFY_H

#include <jni.h>
#include <string>
#include <Android/log.h>
#include<stdlib.h>
#include<pthread.h>
#include <android/log.h>

#define TAG "thduan" // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD

jmethodID mid;
jclass objclass;
jobject mobj;
pthread_t thread;
JavaVM *m_vm;

//jni初始化都会走滴
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    LOGD("JNI_OnLoad begin");

    m_vm = vm;
    JNIEnv *env = NULL;
    jint result = -1;
    if (m_vm) {
        LOGD("m_vm init success");
    } else {
        LOGD("m_vm init failed");
    }

    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        return result;
    }
    return JNI_VERSION_1_4;
}

JNIEnv *getJNIEnv(int *needsDetach) {
    JNIEnv *env = NULL;
    jint result = -1;
    if (m_vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        int status = m_vm->AttachCurrentThread(&env, 0);
        if (status < 0) {
            LOGD("failed to attach current thread");
            return NULL;
        }
        *needsDetach = 1;
    }
    LOGD("GetEnv success");
    return env;
}

JNIEnv *getJNIEnv() {
    JNIEnv *env = NULL;
    m_vm->GetEnv((void **)&env, JNI_VERSION_1_4);

//    if (m_vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
//        int status = m_vm->AttachCurrentThread(&env, 0);
//        if (status < 0) {
//            LOGD("failed to attach current thread");
//            return NULL;
//        }
//    }
    LOGD("GetEnv success");
    return env;
}

/**
 * 将const char类型转换成jstring类型，有问题哦
 */
jstring cStr2Jstring(const char* pat )
{
    // 定义java String类 strClass
    jclass strClass = getJNIEnv()->FindClass("Ljava/lang/String;");
    // 获取java String类方法String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
    jmethodID ctorID = getJNIEnv()->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
    // 建立byte数组
    jbyteArray bytes = getJNIEnv()->NewByteArray((jsize)strlen(pat));
    // 将char* 转换为byte数组
    getJNIEnv()->SetByteArrayRegion(bytes, 0, (jsize)strlen(pat), (jbyte*)pat);
    //设置String, 保存语言类型,用于byte数组转换至String时的参数
    jstring encoding = getJNIEnv()->NewStringUTF("GB2312");
    //将byte数组转换为java String,并输出
    return (jstring)getJNIEnv()->NewObject(strClass, ctorID, bytes, encoding);
}

/**
 * 子线程 回调java，暂时不需要
 */
void *thread_run(void *p) {
    LOGD("thread nativeStart");
    int needsDetach;
    JNIEnv *env = getJNIEnv(&needsDetach);
    LOGD("nativeStart noop callback");
    int i;
    for (int i = 0; i < 10; i++) {
        jstring jstr = env->NewStringUTF("I am maomao");
        LOGD("invoke callback");
        env->CallVoidMethod(mobj, mid, jstr);
        jthrowable exception = env->ExceptionOccurred();
        if (exception) {
            env->ExceptionDescribe();
        }
    }
    if (needsDetach) {
        m_vm->DetachCurrentThread();
    }

    return NULL;

}

void calljava() {
    int needsDetach;
    JNIEnv *env = getJNIEnv(&needsDetach);
    jstring jstr = env->NewStringUTF("I am maomao2");
    LOGD("invoke callback");
    env->CallVoidMethod(mobj, mid, jstr);
    return;
}

void calljava(const char* str) {
    if(!str || (!strcmp(str, "")))
        return;

    int needsDetach;
    JNIEnv *env = getJNIEnv(&needsDetach);
    jstring jstr = env->NewStringUTF(str);
    LOGD("invoke callback");
    env->CallVoidMethod(mobj, mid, jstr);
    return;
}

void calljava(jstring targetName) {
    int needsDetach;
    JNIEnv *env = getJNIEnv(&needsDetach);
    LOGD("nativeStart noop callback");

    jstring jstr = env->NewStringUTF("I am maomao");
    LOGD("invoke callback");
    env->CallVoidMethod(mobj, mid, targetName);

    return;
}


extern "C" {
/**
 * start方法
 */
JNIEXPORT void JNICALL Java_data_easykey_leolu_nativevideodemo_jnin_JNICallBack_nativeStart(JNIEnv *env, jobject thiz) {
    LOGD("java call native nativeStart");

    objclass = env->GetObjectClass(thiz);
    mid = env->GetMethodID(objclass, "callback", "(Ljava/lang/String;)V");
    mobj = env->NewGlobalRef(thiz);
//    pthread_create(&thread, NULL, thread_run, NULL);
}
}

#endif //CARAR_RECNOTIFY_H
